﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Nop.Admin.Models.WindAlert;
using Nop.Admin.WindAlert;
using Nop.Core;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.WindAlert;
using Nop.Services.Directory;
using Nop.Services.ExportImport;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Security;
using Nop.Services.Seo;
using Nop.Services.WindAlert;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Services.Helpers;
using Nop.Web.Framework.Kendoui;

namespace Nop.Admin.Controllers
{
    public partial class WSpotController : BaseAdminController
    {
        #region Fields
        private readonly ILanguageService _languageService;
        private readonly ILocalizationService _localizationService;
        private readonly ILocalizedEntityService _localizedEntityService;
        private readonly ICustomerActivityService _customerActivityService;
        private readonly IExportManager _exportManager;
        private readonly IWorkContext _workContext;
        private readonly IPermissionService _permissionService;
        private readonly AdminAreaSettings _adminAreaSettings;
        private readonly IUrlRecordService _urlRecordService;
        private readonly ISpotService _spotService;
        private readonly ICameraService _cameraService;
        private readonly IDateTimeHelper _dateTimeHelper;

        private readonly ICountryService _countryService;
        private readonly IStateProvinceService _stateProvinceService;

        #endregion

        #region Constructors
        
        public WSpotController(ILanguageService languageService,
            ILocalizationService localizationService, ILocalizedEntityService localizedEntityService,
            ICustomerActivityService customerActivityService, 
            IExportManager exportManager, IWorkContext workContext,
            IPermissionService permissionService,
            AdminAreaSettings adminAreaSettings, IUrlRecordService urlRecordService, 
            ISpotService SpotService, 
            ICameraService CameraService,
            IDateTimeHelper dateTimeHelper
            , ICountryService countryService, IStateProvinceService stateProvinceService)
        {
            this._languageService = languageService;
            this._localizationService = localizationService;
            this._localizedEntityService = localizedEntityService;
            this._customerActivityService = customerActivityService;
            this._exportManager = exportManager;
            this._workContext = workContext;
            this._permissionService = permissionService;
            this._adminAreaSettings = adminAreaSettings;
            this._urlRecordService = urlRecordService;
            this._spotService = SpotService;
            this._cameraService = CameraService;
            this._dateTimeHelper = dateTimeHelper;
            this._countryService = countryService;
            this._stateProvinceService = stateProvinceService;
        }

        #endregion

        #region Utilities

        [NonAction]
        public void UpdateLocales(Spot spot, SpotModel model)
        {
            foreach (var localized in model.Locales)
            {
                _localizedEntityService.SaveLocalizedValue(spot,
                                                               x => x.Name,
                                                               localized.Name,
                                                               localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(spot,
                                                           x => x.Description,
                                                           localized.Description,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(spot,
                                                           x => x.MetaKeywords,
                                                           localized.MetaKeywords,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(spot,
                                                           x => x.MetaDescription,
                                                           localized.MetaDescription,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(spot,
                                                           x => x.MetaTitle,
                                                           localized.MetaTitle,
                                                           localized.LanguageId);

                //search engine name
                var seName = spot.ValidateSeName(localized.SeName, localized.Name, false);
                _urlRecordService.SaveSlug(spot, seName, localized.LanguageId);
            }
        }

        #endregion

        #region Create / Edit / Delete / List

        public ActionResult Index()
        {
            return RedirectToAction("List");
        }

        public ActionResult List()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings))
                return AccessDeniedView();
            return View();
        }

        [HttpPost]
        public ActionResult List(DataSourceRequest command)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings))
                return AccessDeniedView();
            var spots = _spotService.GetAllSpots(command.Page - 1, command.PageSize, true);
            var gridModel = new DataSourceResult
            {
                Data = spots.Select(x => x.ToModel()),
                Total = spots.TotalCount
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult Create()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
                return AccessDeniedView();

            var model = new SpotModel();
            //camera
            model.AvailableCameras = _cameraService.GetAllCameras(true)
                .Select(cr => cr.ToModel())
                .ToList();
            model.SelectedCameraIds = new int[0];
            //locales
            AddLocales(_languageService, model.Locales);

            //default values
            model.Published = true;
            return View(model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Create(SpotModel model, bool continueEditing)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
                return AccessDeniedView();

            //decode description
            model.Description = HttpUtility.HtmlDecode(model.Description);
            foreach (var localized in model.Locales)
                localized.Description = HttpUtility.HtmlDecode(localized.Description);

            if (ModelState.IsValid)
            {
                var spot = model.ToEntity();
                spot.CreatedOnUtc = DateTime.UtcNow;
                spot.UpdatedOnUtc = DateTime.UtcNow;
            
                _spotService.InsertSpot(spot);

                //camera
                var allCameras = _cameraService.GetAllCameras(true);
                foreach (var camera in allCameras)
                    if (model.SelectedCameraIds != null && model.SelectedCameraIds.Contains(camera.Id))
                        spot.Cameras.Add(camera);
                _spotService.UpdateSpot(spot);

                //search engine name
                model.SeName = spot.ValidateSeName(model.SeName, spot.Name, true);
                _urlRecordService.SaveSlug(spot, model.SeName, 0);
                //locales
                UpdateLocales(spot, model);

                //activity log
                _customerActivityService.InsertActivity("AddNewSpot", _localizationService.GetResource("ActivityLog.AddNewSpot"), spot.Name);

                SuccessNotification(_localizationService.GetResource("Admin.WindAlert.Spots.Added"));
                return continueEditing ? RedirectToAction("Edit", new { id = spot.Id }) : RedirectToAction("List");
            }

            //cameras
            model.AvailableCameras = _cameraService.GetAllCameras(true)
                .Select(cr => cr.ToModel())
                .ToList();
            model.SelectedCameraIds = new int[0];

            //locales
            AddLocales(_languageService, model.Locales);

            //default values
            model.Published = true;
            return View(model);
        }

        public ActionResult Edit(int id)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings))
                return AccessDeniedView();

            var spot = _spotService.GetSpotById(id);
            if (spot == null || spot.Deleted)
                //No spot found with the specified id
                return RedirectToAction("List");

            var model = spot.ToModel();
            //locales
            AddLocales(_languageService, model.Locales, (locale, languageId) =>
            {
                locale.Name = spot.GetLocalized(x => x.Name, languageId, false, false);
                locale.Description = spot.GetLocalized(x => x.Description, languageId, false, false);
                locale.MetaKeywords = spot.GetLocalized(x => x.MetaKeywords, languageId, false, false);
                locale.MetaDescription = spot.GetLocalized(x => x.MetaDescription, languageId, false, false);
                locale.MetaTitle = spot.GetLocalized(x => x.MetaTitle, languageId, false, false);
                locale.SeName = spot.GetSeName(languageId, false, false);
            });

            //cameras
            model.AvailableCameras = _cameraService
                .GetAllCameras(true)
                .Select(s => s.ToModel())
                .ToList();
            model.SelectedCameraIds = spot.Cameras.Select(s => s.Id).ToArray();

            return View(model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Edit(SpotModel model, bool continueEditing)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings))
                return AccessDeniedView();

            var spot = _spotService.GetSpotById(model.Id);
            if (spot == null || spot.Deleted)
                //No spot found with the specified id	
                return RedirectToAction("List");

            //decode description
            model.Description = HttpUtility.HtmlDecode(model.Description);
            foreach (var localized in model.Locales)
                localized.Description = HttpUtility.HtmlDecode(localized.Description);

            if (ModelState.IsValid)
            {

                spot = model.ToEntity(spot);
                spot.UpdatedOnUtc = DateTime.UtcNow;
               
                _spotService.UpdateSpot(spot);
                //search engine name
                model.SeName = spot.ValidateSeName(model.SeName, spot.Name, true);
                _urlRecordService.SaveSlug(spot, model.SeName, 0);
                //locales
                UpdateLocales(spot, model);

                //camera
                var allCameras = _cameraService.GetAllCameras(true);
                foreach (var camera in allCameras)
                {
                    if (model.SelectedCameraIds != null &&
                        model.SelectedCameraIds.Contains(camera.Id))
                    {
                        //new role
                        if (spot.Cameras.Count(s => s.Id == camera.Id) == 0)
                            spot.Cameras.Add(camera);
                    }
                    else
                    {
                        //removed role
                        if (spot.Cameras.Count(s => s.Id == camera.Id) > 0)
                            spot.Cameras.Remove(camera);
                    }
                }
                _spotService.UpdateSpot(spot);

                //activity log
                _customerActivityService.InsertActivity("EditSpot", _localizationService.GetResource("ActivityLog.EditSpot"), spot.Name);

                SuccessNotification(_localizationService.GetResource("Admin.WindAlert.Spots.Updated"));
                if (continueEditing)
                {
                    //selected tab
                    SaveSelectedTabIndex();

                    return RedirectToAction("Edit", new { id = spot.Id });
                }
                else
                {
                    return RedirectToAction("List");
                }
            }
            return View(model);
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageSettings))
                return AccessDeniedView();

            var spot = _spotService.GetSpotById(id);
            if (spot == null)
                //No spot found with the specified id	
                return RedirectToAction("List");
            _spotService.DeleteSpot(spot);

            //activity log
            _customerActivityService.InsertActivity("DeleteSpot", _localizationService.GetResource("ActivityLog.DeleteSpot"), spot.Name);

            SuccessNotification(_localizationService.GetResource("Admin.WindAlert.Spots.Deleted"));
            return RedirectToAction("List");
        }
        #endregion   

        #region Comments

        public ActionResult Comments(int? filterBySpotId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageBlog))
                return AccessDeniedView();

            ViewBag.FilterBySpotId = filterBySpotId;
            return View();
        }

        [HttpPost]
        public ActionResult Comments(int? filterBySpotId, DataSourceRequest command)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageBlog))
                return AccessDeniedView();

            IList<SpotComment> comments;
            if (filterBySpotId.HasValue)
            {
                //filter comments by spot
                var spot = _spotService.GetSpotById(filterBySpotId.Value);
                comments = spot.SpotComments.OrderBy(sc => sc.CreatedOnUtc).ToList();
            }
            else
            {
                //load all spot comments
                comments = _spotService.GetAllComments(0,0,null,null);
            }

            var gridModel = new DataSourceResult
            {
                Data = comments.PagedForCommand(command).Select(spotComment =>
                {
                    var commentModel = new SpotCommentModel();
                    commentModel.Id = spotComment.Id;
                    commentModel.SpotId = spotComment.SpotId;
                    commentModel.SpotTitle = spotComment.Spot.Name;
                    commentModel.CustomerId = spotComment.CustomerId;
                    var customer = spotComment.Customer;
                    commentModel.CustomerInfo = customer.IsRegistered() ? customer.Email : _localizationService.GetResource("Admin.Customers.Guest");
                    commentModel.CreatedOn = _dateTimeHelper.ConvertToUserTime(spotComment.CreatedOnUtc, DateTimeKind.Utc);
                    commentModel.Comment = Core.Html.HtmlHelper.FormatText(spotComment.CommentText, false, true, false, false, false, false);
                    return commentModel;
                }),
                Total = comments.Count,
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult CommentDelete(int id)
        {

            if (!_permissionService.Authorize(StandardPermissionProvider.ManageBlog))
                return AccessDeniedView();

            var comment = _spotService.GetSpotCommentById(id);
            if (comment == null)
                throw new ArgumentException("No comment found with the specified id");

            var spot = comment.Spot;
            _spotService.DeleteSpotComment(comment);
            //update totals
            spot.CommentCount = spot.SpotComments.Count;
            _spotService.UpdateSpot(spot);

            return Json(null);
        }


        #endregion  
    }
}
